#include "interrupt.h"
#include "pmm.h"
#include "printf.h"
#include "panic.h"
#include "plic.h"
#include "clint.h"
#include "riscv.h"  // 需包含RISC-V寄存器定义（如mtvec、mie、mstatus等）
extern void trap_entry(void);  // 新增这一行
// 全局中断向量表实例
irq_descriptor_t irq_vector_table[MAX_IRQ_NUM] = {0};

// 初始化中断控制器（CLINT/PLIC）和向量表
void trap_init(void) {
    // 1. 初始化中断向量表（清空所有处理函数，默认禁用）
    for (int i = 0; i < MAX_IRQ_NUM; i++) {
        irq_vector_table[i].handler_count = 0;
        irq_vector_table[i].priority = IRQ_PRIORITY_0;
        irq_vector_table[i].enabled = 0;
        for (int j = 0; j < MAX_HANDLERS_PER_IRQ; j++) {
            irq_vector_table[i].handlers[j] = NULL;
        }
    }

    // 2. 配置中断入口（RISC-V的mtvec寄存器，设置直接模式向量表）
    uint64_t trap_entry_addr = (uint64_t)trap_entry;  // 汇编实现的中断入口
    w_mtvec(trap_entry_addr | 0x1);  // 0x1=直接模式（所有中断跳转到同一入口）

    // 3. 初始化PLIC（平台级中断控制器）和CLINT（核心本地中断控制器）
    plic_init();    // 初始化PLIC（需实现，如设置优先级寄存器）
    clint_init();   // 初始化CLINT（时钟中断，如设置初始比较值）

    // 4. 使能全局中断（M模式）
    w_mstatus(r_mstatus() | MSTATUS_MIE);  // 开启M模式全局中断
    printf("Interrupt system initialized\n");
}

// 注册中断处理函数（支持共享中断，返回0成功，-1失败）
int register_interrupt(irq_num_t irq, interrupt_handler_t h, irq_priority_t prio) {
    if (irq >= MAX_IRQ_NUM || h == NULL || prio > IRQ_PRIORITY_7) {
        return -1;  // 无效参数
    }
    irq_descriptor_t *desc = &irq_vector_table[irq];
    if (desc->handler_count >= MAX_HANDLERS_PER_IRQ) {
        return -1;  // 处理函数数量已满
    }
    // 添加处理函数并更新优先级（取最高优先级）
    desc->handlers[desc->handler_count++] = h;
    if (prio > desc->priority) {
        desc->priority = prio;
        plic_set_priority(irq, prio);  // 更新PLIC硬件优先级
    }
    return 0;
}

// 注销中断处理函数（返回0成功，-1失败）
int unregister_interrupt(irq_num_t irq, interrupt_handler_t h) {
    if (irq >= MAX_IRQ_NUM || h == NULL) {
        return -1;
    }
    irq_descriptor_t *desc = &irq_vector_table[irq];
    for (int i = 0; i < desc->handler_count; i++) {
        if (desc->handlers[i] == h) {
            // 移除函数（覆盖并减少计数）
            desc->handlers[i] = desc->handlers[desc->handler_count - 1];
            desc->handlers[desc->handler_count - 1] = NULL;
            desc->handler_count--;
            return 0;
        }
    }
    return -1;  // 未找到函数
}

// 开启特定中断（更新使能标记并配置PLIC/CLINT）
void enable_interrupt(irq_num_t irq) {
    if (irq >= MAX_IRQ_NUM) return;
    irq_descriptor_t *desc = &irq_vector_table[irq];
    if (desc->enabled) return;  // 已使能

    desc->enabled = 1;
    // 配置硬件使能（PLIC：允许中断发送到当前HART；CLINT：使能时钟中断）
    if (irq == IRQ_TIMER) {
        w_mie(r_mie() | MIE_MTIE);  // 使能M模式时钟中断
    } else {
        plic_enable(irq, r_mhartid());  // 使能PLIC中断到当前HART
    }
}

// 关闭特定中断
void disable_interrupt(irq_num_t irq) {
    if (irq >= MAX_IRQ_NUM) return;
    irq_descriptor_t *desc = &irq_vector_table[irq];
    if (!desc->enabled) return;

    desc->enabled = 0;
    if (irq == IRQ_TIMER) {
        w_mie(r_mie() & ~MIE_MTIE);  // 禁用M模式时钟中断
    } else {
        plic_disable(irq, r_mhartid());  // 禁用PLIC中断
    }
}

// 中断处理核心逻辑（由汇编入口调用，解析cause并分发）
void trap_handler(uint64_t cause, uint64_t epc) {
    // 1. 判断中断类型（异常/中断）
    if ((cause & 0x8000000000000000) == 0) {
        // 异常处理（如页错误，可结合现有VMM模块调试）
        printf("Exception: cause=0x%lx, epc=0x%lx\n", cause, epc);
        panic("Unhandled exception");  // 调用现有panic函数
    }

    // 2. 解析中断源（RISC-V中断cause编码）
    uint64_t irq = cause & 0x7FFFFFFF;
    irq_descriptor_t *desc = NULL;

    switch (irq) {
        case 7:  // M模式时钟中断（CLINT）
            desc = &irq_vector_table[IRQ_TIMER];
            break;
        case 11: // M模式外部中断（PLIC）
            // 从PLIC获取具体中断号（硬件中断号=PLIC返回值+1）
            ;uint32_t plic_irq = plic_claim(r_mhartid());
            if (plic_irq + 1 < MAX_IRQ_NUM) {
                desc = &irq_vector_table[plic_irq + 1];
            }
            break;
        // 可扩展其他中断类型（如软件中断）
        default:
            printf("Unknown interrupt: cause=0x%lx\n", cause);
            panic("Unhandled interrupt");
    }

    // 3. 处理中断（调用所有注册的处理函数，支持共享中断）
    if (desc && desc->enabled) {
        // 支持中断嵌套：仅允许更高优先级中断打断当前处理
        uint64_t current_prio = desc->priority;
        plic_set_threshold(r_mhartid(), current_prio);  // 屏蔽同/低优先级中断

        // 调用所有注册的处理函数
        for (int i = 0; i < desc->handler_count; i++) {
            if (desc->handlers[i]) {
                desc->handlers[i]();  // 执行用户注册的处理逻辑
            }
        }

        // 恢复优先级阈值（允许所有优先级中断）
        plic_set_threshold(r_mhartid(), 0);
    }

    // 4. 通知PLIC中断处理完成（外部中断）
    if (irq == 11 && desc) {
        plic_complete(r_mhartid(), irq - 1);  // 清除PLIC中断状态
    }
}
